[初心者向け]Dataformでテーブル間の依存関係について調べてみた
クラスメソッド株式会社データアナリティクス事業本部所属のニューシロです。
今回はGoogle CloudのサービスであるDataformについて、テーブル間の依存関係について調べてみました。
Dataformを使用した経験がまだ無い方向けの記事です。
前提
Dataformとは
Dataformの紹介についての引用です。
Dataform は、データ アナリストが BigQuery でデータ変換を行う複雑な SQL ワークフローを開発、テスト、バージョン管理、スケジュール設定するためのサービスです。
Dataform を使用すると、データ統合の ELT(抽出、読み込み、変換)プロセスにおけるデータ変換を管理できます。Dataform では、ソースシステムから抽出されたデータを BigQuery に読み込むと、明確に定義されたテスト済みで一連のデータテーブルに変換できます。
よく比較対象に挙がるサービスとしてはdbtがあります。
依存関係とは
Dataformの依存関係についての引用です。
依存関係がある場合、依存オブジェクトの実行は依存関係オブジェクトの実行に依存します。つまり、Dataform は依存関係の後に依存を実行します。依存関係は、依存オブジェクトの SQLX 定義ファイル内で依存関係を宣言することによって定義します。
依存関係の宣言は、SQL ワークフローの依存関係ツリーを構成し、Dataform が SQL ワークフロー オブジェクトを実行する順序を決定します。
今回は実際にテーブルやsqlxファイルを作成し、依存関係について具体的に調べてみました。
依存関係を定義できる対象としてはテーブルの他にカスタムSQLオペレーションやアサーションがあるようですが、今回はテーブル間に限定して調査しました。
本題
今回想定するDataformの実行ケース
ソーステーブルを作成
BigQueryにて、以下のクエリでテーブルを2つ作成します。
CREATE TABLE `dataform_source.source_1` AS SELECT "1" AS id, "apple" AS name UNION ALL SELECT "2" AS id, "orange" AS name UNION ALL SELECT "3" AS id, "banana" AS name;
CREATE TABLE `dataform_source.source_2` AS SELECT "4" AS id, "apple" AS name UNION ALL SELECT "5" AS id, "orange" AS name;
Dataformを作成
sqlxファイルを2件作成しました。あまり複雑なコードだと見づらいため、なるべく簡潔になるようにしました。
config { type: "table", schema: "dataform_table" } SELECT * FROM ${ref("dataform_source", "source_1")} UNION ALL SELECT * FROM ${ref("dataform_source", "source_2")}
config { type: "table", schema: "dataform_table" } SELECT name, COUNT(*) AS cnt FROM ${ref("dataform_table", "first_table")} GROUP BY name
上記コードのように、依存元のテーブルはref()
を用いて指定しています。
依存関係のメリット① 依存関係が可視化される
Dataform画面上でCOMPILED GRAPH
を押下すると、使用テーブルやsqlxファイルについて図示されます。
ここで依存関係を設定するメリットがわかるのですが、そのためにまずは依存関係を設定せずに図を表示してみましょう。
試しに、first_table.sqlx
, second_table.sqlx
についてFROM ${ref("dataform_source", "source_1")}
をFROM dataform_souce.source_1
のように、ref()
を用いない形で書き換え、COMPILED GRAPH
を押下すると以下の図が表示されます(プロジェクト名は伏せてあります)。
ただテーブルが4つ並んだだけの図となります。
しかし、元のコードのようにfirst_table.sqlx
, second_table.sqlx
についてref()
を用いて依存元テーブルを設定することで以下のように表示されます。
このように依存関係が可視化され、データフローを簡単に理解することができます。
依存関係のメリット② sqlxファイル実行時に依存関係のあるsqlxファイルも併せて実行できる
BigQueryデータソース、sqlxファイルの説明
使用している2つのBigQueryデータソースと、2つのsqlxファイルについて簡単に説明します。
source_1
- 今回使用するBigQueryデータソース①
+----+--------+ | id | name | +----+--------+ | 1 | apple | | 2 | orange | | 3 | banana | +----+--------+
source_2
- 今回使用するBigQueryデータソース②
+----+--------+ | id | name | +----+--------+ | 4 | apple | | 5 | orange | +----+--------+
first_table.sqlx
- テーブル
source_1
とテーブルsource_2
を結合する
- テーブル
SELECT * FROM ${ref("dataform_source", "source_1")} UNION ALL SELECT * FROM ${ref("dataform_source", "source_2")} # 結果 +----+--------+ | id | name | +----+--------+ | 1 | apple | | 2 | orange | | 3 | banana | | 4 | apple | | 5 | orange | +----+--------+
second_table.sqlx
first_table
に対してGROUP BY
句でname
ごとの件数を出力する
SELECT name, COUNT(*) AS cnt FROM ${ref("dataform_table", "first_table")} GROUP BY name # 結果 +--------+-----+ | name | cnt | +--------+-----+ | apple | 2 | | banana | 1 | | orange | 2 | +--------+-----+
以上の2つのBigQueryデータソースと、2つのsqlxファイルを使用してDataformを実行します。
Dataformのワークフロー実行
依存関係について確認するため、Dataformのワークフローを実行していきます。
データ処理の流れについて把握するため、source_2
にレコードを1件追加します。
INSERT `dataform_source.source_2` (id, name) VALUES("6", "apple"); # 実行後のsource_2レコード +----+--------+ | id | name | +----+--------+ | 4 | apple | | 5 | orange | | 6 | apple | +----+--------+
この後に、second_table.sqlx
を実行してみます。
図から確認できるように、second_table.sqlx
の元であるfirst_table
自体には変更が無いため、second_table.sqlx
を実行してももちろん変化はありません。
しかし、ここで依存関係を利用することができます。まずはDataform画面上で実行するsqlxファイルを選択します。
その後「依存関係を含める」にチェックを入れます。
この状態でsecond_table.sqlx
を実行すると、second_table.sqlx
だけではなく、依存関係があるfirst_table.sqlx
まで実行してくれます。
これにより、source_2
に追加した1件のレコードが、first_table
にも反映され、その後second_table
にも反映されます。
実行結果
# second_table.sqlxを実行した結果 # 依存関係を含めないで実行した場合 +--------+-----+ | name | cnt | +--------+-----+ | apple | 2 | | banana | 1 | | orange | 2 | +--------+-----+ # 依存関係を含めて実行した場合 # appleの数が追加されている +--------+-----+ | name | cnt | +--------+-----+ | apple | 3 | | banana | 1 | | orange | 2 | +--------+-----+
このように、実行したsqlxファイル以外にも必要なsqlxファイルを実行してくれます。とても便利ですね。
補足
チェックを入れる画面で、「依存関係を含める」だけでなく、「依存者を含める」「完全に更新して実行する」がありました。
「依存者を含める」にチェックを入れると、「依存関係を含める」とは逆で、実行するsqlxファイルに依存するアクションを実行してくれるようでした。
また、「完全に更新して実行する」にチェックを入れると、増分テーブルの場合でもテーブルを再作成してくれるようです。
最後に感想
今回のようなシンプルな例だと可視化されなくてもそこまで問題は無いですが、テーブル数が増えると、可視化されることによってデータフローへの理解にとても役立つなと思いました。
また、自分が書いたデータフローが目に見えるようになることで作成するモチベーションも上がりそうですね。